class Compiler {
    constructor (vm) {
        this.el = vm.$el
        this.vm = vm

        this.compile(this.el)
    }

    compile(el) {
        // 编译模版，处理文本节点和元素节点
        let childNodes = el.childNodes
        Array.from(childNodes).forEach(node => {
            if(this.isTextNode(node)) {
                this.compileText(node)
            } else if(this.isElementNode(node)) {
                this.compileElement(node)
            }
            // 递归调用 compile 编译深层的节点
            if(node.childNodes && node.childNodes.length) {
                this.compile(node)
            }
        })
    }

    compileElement(node) {
        // 编译元素节点，处理指令
        // console.log(Array.from(node.attributes))
        Array.from(node.attributes).forEach(attr => {
            let attrName = attr.name
            if(!this.isDirective(attrName)) return
            attrName = attrName.substr(2)
            let key = attr.value
            this.update(node, key, attrName)
        })
    }

    update (node, key, attrName) {
        let subName = attrName.split(':')[1]
        let attrMain = attrName.split(':')[0]
        let updateFn = this[attrMain + 'Updater']
        let value = attrMain==='on' ? this.vm[key.split('(')[0]] : this.vm[key]
        updateFn && updateFn.call(this, node, value, key, subName)
    }

    textUpdater (node, value, key) {
        // 处理 v-text 指令
        node.textContent = value
        // 创建 watcher 
        new Watcher(this.vm, key, newValue => {
            node.textContent = newValue
        })
    }

    modelUpdater (node, value, key) {
        // 处理表单数据
        node.value = value
        // 创建 watcher 
        new Watcher(this.vm, key, newValue => {
            node.value = newValue
        })
        node.addEventListener('input', () => {
            this.vm[key] = node.value
        })
    }

    htmlUpdater (node, value, key) {
        // 处理 v-html
        node.innerHTML = value
        // 创建 watcher 
        new Watcher(this.vm, key, newValue => {
            node.innerHTML = newValue
        })
    }

    onUpdater (node, fn, key, eventName) {
        // 提取 key 中的参数
        let argArr = []
        let argstr = key.match(/^.*\((.*)\)/)
        argstr = (argstr && argstr.length>1 ? argstr[1] : '')
        argstr && (argArr = argstr.split(',').map(item => {
            let removeQuote = item.match(/^[\'|\"](.*)[\'|\"]$/)
            let itemValue = removeQuote ? removeQuote[1] : item
            return itemValue.trim()
        }))
        console.log(argArr);
        
        node.addEventListener(eventName, (val) => {
            switch(node.localName) {
                case 'input':
                    fn.call(this.vm, node.value)
                    break
                default:
                    fn.call(this.vm, ...argArr)
                    break
            }
        })
    }

    compileText(node) {
        // 编译文本节点，处理插值表达式
        // console.dir(node);
        const reg = /\{\{(.+?)\}\}/  // 匹配插值表达式
        let value = node.textContent
        if(reg.test(value)) {
            let key = RegExp.$1.trim()
            node.textContent = value.replace(reg, this.vm[key])

            // 创建 watcher 
            new Watcher(this.vm, key, newValue => {
                node.textContent = newValue
            })
        }
    }

    isDirective(attrName) {
        // 判断元素属性是否是指令
        return attrName.startsWith('v-')
    }

    isTextNode(node) {
        // 判断是否是文本节点
        return node.nodeType === 3
    }

    isElementNode(node) {
        // 判断是否是元素节点
        return node.nodeType === 1
    }
}